home *** CD-ROM | disk | FTP | other *** search
- /*
- * This file provides the necessary parts for making
- * the Amiga version of AT&T awk fly.
- *
- * Compile with SAS/C 6.51 to get maximum functionality.
- * Needs V36+ system includes to compile.
- * Will use arp.library for pattern matching if it is
- * available when running under pre-V36 AmigaDOS.
- *
- * This file is Copyright (c) 1994 Torsten Poulin
- * Freely redistributable.
- *
- * Torsten Poulin (torsten@diku.dk)
- * 2-Jun-94
- */
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
-
- static const char AMIGAver[] = "\0$VER: AT&T-awk 1.0 (2.6.94)";
-
- #ifdef __SASC
-
- #include <errno.h>
-
- #include <workbench/startup.h>
- #include <libraries/dos.h>
- #include <libraries/dosextens.h>
- #include <exec/memory.h>
- #include <dos/var.h>
- #include <dos/dostags.h>
- #include <dos/dosasl.h>
- #include <proto/dos.h>
- #include <proto/exec.h>
-
- extern char __stdiowin[];
- extern char __stdiov37[];
- extern long __stack = 64 * 1024; /* This should be more than enough */
-
- extern struct WBStartup *_WBenchMsg;
- int main(int, void *);
-
- static int argc; /* arg count */
- static char **targv, **argv; /* arg pointers */
-
- #ifdef USE_ARP
-
- struct ARPAnchorPath {
- void *ARP_private1;
- void *ARP_private2;
- LONG ARP_private3;
- LONG ARP_private4;
- BYTE ARP_ap_Flags;
- BYTE ARP_private5;
- WORD ARP_ap_Strlen;
- struct FileInfoBlock ARP_ap_Info;
- BYTE ARP_ap_Buf[1];
- };
-
- #define ARP_APB_DOWILD 0L
- #define ARP_APF_DOWILD (1L << ARP_APB_DOWILD)
-
- #pragma libcall ArpBase ArpFindFirst 1bc 8002
- #pragma libcall ArpBase ArpFindNext 1c2 801
- #pragma libcall ArpBase ArpFreeAnchorChain 1c8 801
-
- LONG ArpFindFirst(char *, struct ARPAnchorPath *);
- LONG ArpFindNext(struct ARPAnchorPath *);
- VOID ArpFreeAnchorChain(struct ARPAnchorPath *);
-
- struct Library *ArpBase;
-
- #endif
-
- #endif /* __SASC */
-
-
-
- /*
- * Pipes are implemented in a simplistic
- * MS-DOS kind of way using temporary files for now.
- * Matt Dillons's FifoLib would be a better solution, though.
- * The official queue.handler (pipe.handler in V33) isn't a
- * good candidate as it doesn't handle broken pipes gracefully.
- *
- * The present versions of popen() og pclose() call system()
- * with "command >TMPFILE" and "command TMPFILE" when the pipe
- * is opened for reading and writing, respectively.
- */
-
- #define MAX_CMD_LEN 128
-
- struct pipe_info {
- FILE *handle;
- int ret_val;
- char tmp_name[L_tmpnam+1];
- char cmd[MAX_CMD_LEN+1];
- };
-
- static struct pipe_info pipes[FOPEN_MAX];
- static char pipe_cmd[MAX_CMD_LEN+2+L_tmpnam+1];
-
- FILE *popen(const char *command, const char *type)
- {
- int pipe;
-
- if (strlen(command) > MAX_CMD_LEN) return NULL;
-
- for (pipe = 0; pipe < FOPEN_MAX; pipe++)
- if (!pipes[pipe].handle) break;
- if (pipe == FOPEN_MAX) return NULL; /* no available phandle */
-
- if (*type == 'r') {
- /*
- * pipe opened for reading
- */
- strcpy(pipes[pipe].tmp_name, tmpnam(NULL));
- sprintf(pipe_cmd, "%s >%s", command, pipes[pipe].tmp_name);
- pipes[pipe].ret_val = system(pipe_cmd);
-
- if (!(pipes[pipe].handle = fopen(pipes[pipe].tmp_name, "r"))) {
- /*
- * Something went wrong, clean up.
- */
- memset(&pipes[pipe], 0, sizeof(struct pipe_info));
- remove(pipes[pipe].tmp_name);
- }
- }
- else if (*type == 'w') {
- /*
- * pipe opened for writing
- */
- strcpy(pipes[pipe].tmp_name, tmpnam(NULL));
- if (pipes[pipe].handle = fopen(pipes[pipe].tmp_name, "w"))
- strcpy(pipes[pipe].cmd, command);
- }
-
- return pipes[pipe].handle;
- }
-
- int pclose(FILE *stream)
- {
- int pipe;
- int ret = 127;
-
- for (pipe = 0; pipe < FOPEN_MAX; pipe++)
- if (pipes[pipe].handle == stream) {
-
- if (!*pipes[pipe].cmd) {
- /*
- * No cmd, so it must be a pipe opened for reading.
- */
- if (stream) {
- fclose(stream);
- remove(pipes[pipe].tmp_name);
- }
- ret = pipes[pipe].ret_val;
- memset(&pipes[pipe], 0, sizeof(struct pipe_info));
- break;
- }
- else {
- /*
- * It was a pipe opened for writing, so we have
- * to feed the data to the command.
- */
- sprintf(pipe_cmd, "%s %s", pipes[pipe].cmd, pipes[pipe].tmp_name);
- if (stream) {
- fclose(stream);
- ret = system(pipe_cmd);
- remove(pipes[pipe].tmp_name);
- }
- memset(&pipes[pipe], 0, sizeof(struct pipe_info));
- break;
- }
- }
- return ret;
- }
-
- #ifdef __SASC
- /*
- * Erase any remaining temporary files.
- */
- void __stdargs _STD_30000_tmpfilecleanup(void)
- {
- int pipe;
-
- for (pipe = 0; pipe < FOPEN_MAX; pipe++) {
- if (pipes[pipe].handle) fclose(pipes[pipe].handle);
- if (*pipes[pipe].tmp_name) remove(pipes[pipe].tmp_name);
- }
- }
- #endif
-
-
- static char *empty_env = NULL; /* A default empty environment */
-
- #ifndef __SASC
-
- char **environ = &empty_env; /* An empty environment variable list */
-
- #else /* __SASC */
-
- char **environ; /* Unix style environment variable list */
- static long env_size = 0;
-
- /*
- * Build a UNIX style environ variable from the AmigaDOS environment.
- * Can only recognize local shell variables.
- *
- * Stolen from David Gay's Amiga port of GNU Emacs :-)
- */
-
- static void make_environ(void)
- {
- int env_count = 0;
- long env_len = 0;
- struct LocalVar *scan_env;
- char **new_environ, *env_text;
- struct Process *process;
-
- if (DOSBase->dl_lib.lib_Version < 37) {
- environ = &empty_env; /* no local vars in pre-V37, sorry */
- return;
- }
-
- process = (struct Process *) FindTask(NULL);
-
- for (scan_env = (struct LocalVar *) process->pr_LocalVars.mlh_Head;
- scan_env->lv_Node.ln_Succ;
- scan_env = (struct LocalVar *) scan_env->lv_Node.ln_Succ)
- if (scan_env->lv_Node.ln_Type == LV_VAR &&
- !(scan_env->lv_Flags & (GVF_GLOBAL_ONLY | GVF_BINARY_VAR))) {
- /*
- * We only handle local text variables
- */
- env_count++;
- env_len += 2 + strlen(scan_env->lv_Node.ln_Name) + scan_env->lv_Len;
- }
-
- env_size = sizeof(char *) * (1 + env_count) + env_len;
- new_environ = environ = AllocMem(env_size, MEMF_CLEAR);
-
- env_text = (char *) (environ + (1 + env_count));
- if (!environ) environ = &empty_env;
- else {
- for (scan_env = (struct LocalVar *) process->pr_LocalVars.mlh_Head;
- scan_env->lv_Node.ln_Succ;
- scan_env = (struct LocalVar *) scan_env->lv_Node.ln_Succ)
- if (scan_env->lv_Node.ln_Type == LV_VAR &&
- !(scan_env->lv_Flags & (GVF_GLOBAL_ONLY | GVF_BINARY_VAR))) {
- /*
- * We only handle local text variables
- */
- char *env_name = scan_env->lv_Node.ln_Name;
- int env_len = scan_env->lv_Len;
-
- *new_environ++ = env_text;
- while (*env_name) *env_text++ = *env_name++;
- *env_text++ = '=';
- env_name = scan_env->lv_Value;
- while (env_len--) *env_text++ = *env_name++;
- *env_text++ = '\0';
- }
- *new_environ = 0;
- }
- }
-
- void __stdargs _STD_250_envcleanup(void)
- {
- if (environ != &empty_env) FreeMem(environ, env_size);
- }
-
-
- #define SQUOTE '\''
- #define DQUOTE '"'
- #define ESCAPE '*'
-
- #define LINE_GROW 128
-
- #define isspace(c) ((c == ' ')||(c == '\t') || (c == '\n'))
-
- static char *parambuf;
- static int paramlen = LINE_GROW, idx = 0;
-
- static void copychar(char c)
- {
- if (idx < paramlen) parambuf[idx++] = c;
- else {
- paramlen += LINE_GROW;
- if (!(parambuf = realloc(parambuf, paramlen))) exit(20);
- parambuf[idx++] = c;
- }
- }
-
-
- #define NAMELEN 255
-
- static char pattern[NAMELEN+1];
- static struct AnchorPath *ap;
-
- static char *patternmatch(char *line)
- {
- int ispattern = 0;
- char *c;
-
- for (c = pattern; *line && !isspace(*line); ++line)
- if (c - pattern < NAMELEN) {
- if (*line == '~' || *line == '#' || *line == '?' || *line == '*' ||
- *line == '%' || *line == '(' || *line == '[' || *line == '|')
- ispattern = 1;
- *c++ = *line;
- }
- *c = '\0';
-
- #ifndef USE_ARP
- if (DOSBase->dl_lib.lib_Version < 36) ispattern = 0;
- #else
- if (ispattern && DOSBase->dl_lib.lib_Version < 36) {
- struct ARPAnchorPath *ArpAP;
-
- if (!(ArpAP = malloc(sizeof(struct ARPAnchorPath)+NAMELEN+1)))
- exit(20);
- memset(ArpAP, 0, sizeof(struct ARPAnchorPath) + NAMELEN + 1);
-
- ArpAP->ARP_ap_Strlen = NAMELEN;
- ArpAP->ARP_ap_Flags = ARP_APF_DOWILD;
-
- if (ArpBase = OpenLibrary("arp.library", 39L)) {
- if ((ArpFindFirst(pattern, ArpAP)) == 0)
- do
- {
- if (ArpAP->ARP_ap_Info.fib_DirEntryType < 0 ) {
- ++argc;
- for (c = ArpAP->ARP_ap_Buf; *c; ++c) copychar(*c);
- copychar('\0');
- }
- } while ((ArpFindNext(ArpAP)) == 0);
- ArpFreeAnchorChain(ArpAP);
- CloseLibrary(ArpBase); /* no reason to let it stay open */
- }
- else ispattern = 0; /* No arp.library => no patterns */
- free(ArpAP);
- }
- #endif
-
- if (ispattern) {
- if ((MatchFirst(pattern, ap)) == 0)
- do
- {
- if (ap->ap_Info.fib_DirEntryType < 0) {
- ++argc;
- for (c = ap->ap_Buf; *c; ++c) copychar(*c);
- copychar('\0');
- }
- } while ((MatchNext(ap)) == 0);
- MatchEnd(ap);
- }
-
- if (!ispattern) {
- ++argc;
- for (c = pattern; *c; ++c) copychar(*c);
- copychar('\0');
- }
-
- return line;
- }
-
-
- void __stdargs __main(char *line)
- {
- int ret, i;
-
- if (!(parambuf = malloc(paramlen))) exit(20);
- if (!(ap = malloc(sizeof(struct AnchorPath) + NAMELEN + 1))) exit(20);
- memset(ap, 0, sizeof(struct AnchorPath) + NAMELEN + 1);
- ap->ap_Strlen = NAMELEN;
-
- for (argc = 0;;) {
- while (isspace(*line)) ++line;
- if (!*line) break;
- if (*line == SQUOTE) {
- ++line;
- ++argc;
- while (*line != SQUOTE && *line) {
- if (*line == ESCAPE) {
- line++;
- if (!*line) {
- copychar('\0');
- goto linedone;
- }
- }
- copychar(*line++);
- }
- if (*line) ++line;
- copychar('\0');
- }
- else if (*line == DQUOTE) {
- ++line;
- ++argc;
- while (*line != DQUOTE && *line) {
- if (*line == ESCAPE) {
- line++;
- if (!*line) {
- copychar('\0');
- goto linedone;
- }
- }
- copychar(*line++);
- }
- if (*line) ++line;
- copychar('\0');
- }
- else { /* non-quoted arg */
- line = patternmatch(line);
- if (!*line) break;
- }
- } /* while */
- linedone:
-
- free(ap);
-
- if (argc) {
- if (!(argv = malloc((argc + 1) * sizeof(char *)))) exit(20);
- memset(argv, 0, (argc + 1) * sizeof(char *));
-
- argv[0] = parambuf;
- for (i = 1; i < argc; )
- if (!*parambuf++) argv[i++] = parambuf;
- }
-
- targv = (argc == 0) ? (char **) _WBenchMsg : (char **) argv;
-
- make_environ();
-
- /*
- * Call user's main program
- */
-
- ret = main(argc, targv); /* call main function */
-
- exit(ret);
- }
-
-
-
- /* Replacement for the SAS/C 6.51 system() function.
- * This version uses the UserShell which by default
- * is the same as the boot shell but can be changed
- * by the user; e.g., to WShell.
- *
- * Does nothing if passed a NULL pointer or an empty string.
- */
-
- int system(const char *s)
- {
- int result;
- struct TagItem tags[2];
-
- if (!s || !*s) return 0;
-
- if (DOSBase->dl_lib.lib_Version < 36L) {
- Execute((char *) s, NULL, NULL);
- result = 0; /* nothing reasonable is available... */
- }
- else {
- tags[0].ti_Tag = SYS_UserShell; tags[0].ti_Data = TRUE;
- tags[1].ti_Tag = TAG_END; tags[1].ti_Data = NULL;
- if ((result = (int) System((char *) s, tags)) == -1)
- errno = EOSERR;
- }
- return result;
- }
-
- #endif /* __SASC */
-